unit DBEditBuscaDados;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Mask, DB,DBCtrls, DBGrids, ZDataSet;

type
  //TFillFieldsEvent = procedure (Sender: TObject) of object;
  TDBEditBuscaDados = class(TDBEdit)
  private
    GridList: TDBGrid;
    FFillFieldsNotInBlank: boolean;
    FFillFieldsOnKeyPress: boolean;
    FDataSourteList: TDataSource;
    FQueryList: TZQuery;
    FParamsCount: integer;
    FMinChars: integer;
    FFieldsToFill: TStrings;
    FSQL: TStrings;
    FTipoDataSet: String;
    FCampoAntes: String;
    procedure SetSQL(const Value: TStrings);
    procedure SetFieldsToFill(const Value: TStrings);
    procedure EscondeGrid;
    procedure AtivaGrid;
    procedure CarregaDados;
    //procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
    procedure CMExit(var Message: TCMExit); message CM_EXIT;
    //FOnFillFields: TFillFieldsEvent;
    //
    {
    if Assigned(FOnFillFields) then
    FOnFillFields(Self);    }

  protected
    { Protected declarations }

  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure KeyUp(var Key: Word; Shift: TShiftState); override;

    function GetAllFields: TStringList;
    procedure GridClick(Sender: TObject);
    procedure FillFieldsNow;


  published
    //property OnFillFields: TFillFieldsEvent read FOnFillFields write FOnFillFields;
    property ParamsCount: integer read FParamsCount write FParamsCount;
    property MinChars: integer read FMinChars write FMinChars;
    property FillFieldsNotInBlank: boolean read FFillFieldsNotInBlank write FFillFieldsNotInBlank;
    property FillFieldsOnKeyPress: boolean read FFillFieldsOnKeyPress write FFillFieldsOnKeyPress;

    property DataFieldsToFill: TStrings read FFieldsToFill write SetFieldsToFill;
    property DataSQL: TStrings read FSQL write SetSQL;

  end;


procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('MRSoftware', [TDBEditBuscaDados]);
end;

{ TDBEditBuscaDados }

procedure TDBEditBuscaDados.AtivaGrid;
begin
  if not GridList.Visible  then
  begin
    GridList.Visible := false;
    GridList.Visible:= true;
    GridList.Top := Top + Height;
    GridList.Width := Width;
    GridList.Height := 150;
    GridList.Left := left;
    GridList.Parent := Parent;
    GridList.BringToFront;
  end;

end;

procedure TDBEditBuscaDados.CarregaDados;
var
    vCampos: TStringList;
    i: integer;
    vQuery: TDataSet;
begin
    EscondeGrid;
    Self.text := FQueryList.FieldByName(self.DataField).AsString;
    if FFieldsToFill.Count <= 0 then
        Exit;

    vCampos := TStringList.Create;

    if FFieldsToFill[0] = 'ALL' then
        vCampos.Assign(GetAllFields)
    else
        vCampos.Assign(FFieldsToFill);

    vQuery := Self.DataSource.DataSet;

    for i := 0 to vCampos.Count - 1 do
    begin
        {if FTipoDataSet = 'Query' then
        begin
            if not FFillFieldsNotInBlank then
                if length(Trim((vQuery as TZQuery).FieldByName(vCampos[i]).AsString)) > 0 then
                    continue;

            (vQuery as TZQuery).FieldByName(vCampos[i]).AsString :=
                FQueryList.FieldByName(vCampos[i]).AsString;
        end else if FTipoDataSet = 'Table' then
        begin
            if not FFillFieldsNotInBlank then
                if length(Trim((vQuery as TZTable).FieldByName(vCampos[i]).AsString)) > 0 then
                    continue;

            (vQuery as TZTable).FieldByName(vCampos[i]).AsString :=
                FQueryList.FieldByName(vCampos[i]).AsString;
        end;
        }

        if not FFillFieldsNotInBlank then
             if length(Trim((vQuery as TDataSet).FieldByName(vCampos[i]).AsString)) > 0 then
                    continue;

        (vQuery as  TDataSet).FieldByName(vCampos[i]).AsString :=
             FQueryList.FieldByName(vCampos[i]).AsString;
    end;

    vCampos.Free;
    //vQuery.Free;

end;

procedure TDBEditBuscaDados.CMExit(var Message: TCMExit);
begin
  inherited;
  if not GridList.Focused then
      EscondeGrid;

end;

constructor TDBEditBuscaDados.Create(AOwner: TComponent);
begin
  inherited;
  FFieldsToFill := TStringList.Create;
  FFieldsToFill.Text := '';
  FSQL := TStringList.Create;
  Fsql.Text := '';
  FParamsCount := 1;
  FFillFieldsNotInBlank := false;
  FCampoAntes := '';
end;

destructor TDBEditBuscaDados.Destroy;
begin
  inherited;
end;

procedure TDBEditBuscaDados.EscondeGrid;
begin
  if not (GridList = nil) then
    GridList.Visible := false;

end;


procedure TDBEditBuscaDados.FillFieldsNow;
begin
    CarregaDados;
end;

function TDBEditBuscaDados.GetAllFields: TStringList;
var
    retorno: TStringList;
    i : integer;
    vQuery: TZQuery;

begin
    vQuery := TZQuery.Create(parent);
    try
        if Self.DataSource.DataSet is TZQuery then
        begin
            vQuery.Connection := (Self.DataSource.DataSet as TZQuery).Connection;
            FTipoDataSet := 'Query';
        end
        else if Self.DataSource.DataSet is TZTable then
        begin
            vQuery.Connection := (Self.DataSource.DataSet as TZTable).Connection;
            FTipoDataSet := 'Table';
        end;
    except
        FTipoDataSet := 'ERRO';
    end;
    vQuery.SQL.Clear;
    vQuery.SQL.AddStrings(FSQL);
    vQuery.Open;


    retorno := TStringList.Create;

    for i := 0 to vQuery.FieldCount - 1 do
    begin
        retorno.Add(vQuery.Fields[i].FieldName);
    end;

    result := Retorno;
    //retorno.Free;
    vQuery.Free;
end;

procedure TDBEditBuscaDados.GridClick(Sender: TObject);
begin
    CarregaDados;
end;

procedure TDBEditBuscaDados.KeyUp(var Key: Word; Shift: TShiftState);
var
    i: integer;
    vCampo: String;
begin
  inherited;

  if GridList = nil then
  begin
    FQueryList := TZQuery.Create(parent);
    try
        if Self.DataSource.DataSet is TZQuery then
        begin
            FQueryList.Connection := (Self.DataSource.DataSet as TZQuery).Connection;
            FTipoDataSet := 'Query';
        end
        else if Self.DataSource.DataSet is TZTable then
        begin
            FQueryList.Connection := (Self.DataSource.DataSet as TZTable).Connection;
            FTipoDataSet := 'Table';
        end;
    except
        FTipoDataSet := 'ERRO';
    end;
    FQueryList.SQL.Clear;
    FQueryList.SQL.AddStrings(FSQL);

    FDataSourteList := TDataSource.Create(Parent);
    FDataSourteList.DataSet := FQueryList;

    GridList := TDBGrid.Create(Parent);
    GridList.Visible := false;
    GridList.DataSource := FDataSourteList;
    GridList.OnDblClick := GridClick;
    GridList.ReadOnly := true;
    GridList.Options := [dgTitles,dgColumnResize,dgColLines,dgRowLines,dgTabs,
        dgRowSelect,dgConfirmDelete,dgCancelOnExit,dgTitleClick,dgTitleHotTrack,
        dgIndicator];
  end;

  AtivaGrid;


  if (key = 13) then
  begin
    CarregaDados;
  end else if key = 27 then
  begin
    EscondeGrid;
  end else if (key = 40) then
  begin
    FQueryList.Next;
  end else if (key = 38) then
  begin
    FQueryList.Prior;
  end else if (Length(text) >= FMinChars) then
  begin
    vCampo := Self.Text;
    if vCampo <> FCampoAntes then
    begin
        vCampo := '%'+ vCampo + '%';
        FQueryList.Close;
        for i := 1 to ParamsCount  do
        begin
            FQueryList.ParamByName('p'+FormatFloat('00',i)).AsString := vCampo;
        end;
        FQueryList.Open;
    end;
    if FFillFieldsOnKeyPress then
        CarregaDados;
  end;

  FCampoAntes := self.Text;


end;

procedure TDBEditBuscaDados.SetFieldsToFill(const Value: TStrings);
begin
    FFieldsToFill.Assign(Value);
end;

procedure TDBEditBuscaDados.SetSQL(const Value: TStrings);
begin
    FSQL.Assign(Value);

    if not (GridList = nil) then
    begin
        if FQueryList.Active then
            FQueryList.Close;
        FQueryList.SQL.Clear;
        FQueryList.SQL.AddStrings(Value);
    end;

    SetFieldsToFill(GetAllFields);

end;

end.
